/*
 * Copyright 2008 Zoundry LLC, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.zoundry.gaedt.core.util;

import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

/**
 * A simple synchronous encryption class.  This implementation uses DES as the
 * encryption algorithm, and generates the secret key from a passphrase.
 */
public class ZGaeEncrypter
{
    // 8-byte Salt
    byte[] sSalt = {
            (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56, (byte) 0x35, (byte) 0xE3,
            (byte) 0x03
    };

    private Cipher ecipher;
    private Cipher dcipher;
    private int iterationCount = 19;

    /**
     * C'tor.
     *
     * @param aPassPhrase
     */
    public ZGaeEncrypter(String aPassPhrase)
    {
        try
        {
            // Create the key
            KeySpec keySpec = new PBEKeySpec(aPassPhrase.toCharArray(), sSalt, iterationCount);
            SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
            ecipher = Cipher.getInstance(key.getAlgorithm());
            dcipher = Cipher.getInstance(key.getAlgorithm());

            // Prepare the parameter to the ciphers
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(sSalt, iterationCount);

            // Create the ciphers
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
    }

    /**
     * Encrypts the given plaintext into a ciphertext, then base64 encodes it
     * and returns that as the result.
     *
     * @param aString
     */
    public String encrypt(String aString)
    {
        try
        {
            // Encode the string into bytes using utf-8
            byte[] utf8 = aString.getBytes("UTF8");
            // Encrypt
            byte[] enc = ecipher.doFinal(utf8);
            // Encode bytes to base64 to get a string
            return new sun.misc.BASE64Encoder().encode(enc);
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
        return null;
    }

    /**
     * Decrypts the given base64 encoded ciphertext back into its original
     * plaintext.
     *
     * @param aString
     */
    public String decrypt(String aString)
    {
        try
        {
            // Decode base64 to get bytes
            byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(aString);
            // Decrypt
            byte[] utf8 = dcipher.doFinal(dec);
            // Decode using utf-8
            return new String(utf8, "UTF8");
        }
        catch (Exception e)
        {
            ZGaeUtil.logError(e);
        }
        return null;
    }
}
